/*
 * Created by Jaren at 2022/10/28 17:42
 */
import 'dart:convert';
import 'dart:typed_data';

import 'package:binary/src/boxed_int.dart';
import 'package:inmotion_protocol/base/vehicle_data.dart';
import 'package:inmotion_protocol/common/compact.dart';
import 'package:inmotion_protocol/common/exceptions.dart';
import 'package:inmotion_protocol/common/mode.dart';
import 'package:inmotion_protocol/common/product_model.dart';
import 'package:inmotion_protocol/common/product_version.dart';
import 'package:inmotion_protocol/lorin/bean/base/real_time_info.dart';
import 'package:inmotion_protocol/lorin/bean/base/vehicle_real_time_info.dart';
import 'package:inmotion_protocol/lorin/bean/euc/euc_real_time_data.dart';
import 'package:inmotion_protocol/util/byte_util.dart';

class AllV13RealTimeData extends AllRealTimeData<V13RealTimeInfo, V13RealTimeState, V13RealTimeError> {
  AllV13RealTimeData(V13RealTimeInfo realTimeInfo, V13RealTimeState realTimeState, V13RealTimeError realTimeError) : super(realTimeInfo, realTimeState, realTimeError);
}

class V13VehicleSynthesizeRealTimeInfo extends VehicleSynthesizeRealTimeInfo<CommonVehicleRealTimeInfo, V13RealTimeState, V13RealTimeError> {
  V13VehicleSynthesizeRealTimeInfo(CommonVehicleRealTimeInfo commonVehicleRealTimeInfo, V13RealTimeState realTimeState, V13RealTimeError realTimeError) : super(commonVehicleRealTimeInfo, realTimeState, realTimeError);
}

/// 实时信息
class V13RealTimeInfo extends EucRealTimeInfo {
  V13RealTimeInfo(ProductModel model, VersionWrapper version) : super(model, version);

  Int16 chargeVoltage = Int16.zero; // 充电电压
  Int16 chargeCurrent = Int16.zero; // 充电电流

  Int16 acceleration = Int16.zero; // 加速度

  Int8 batteryMaxCellTemp = Int8.zero; // 电池电芯最高温度
  Int8 batteryMaxBmsTemp = Int8.zero; // 电池BMS最高温度

  Uint16 rtOverSpeedTiltBackThr = Uint16.zero; // 实时超速翘板速度阈值
  Uint16 rtOverSpeedWarningThr = Uint16.zero; // 实时超速报警速度阈值
  Uint16 rtOverOutputTiltBackThr = Uint16.zero; // 实时输出饱和翘板阈值
  Uint16 rtOverOutputWarningThr = Uint16.zero; // 实时输出饱和报警阈值
  Uint16 rtOverBusCurrentTiltBackThr = Uint16.zero; // 实时过流翘板阈值
  Uint16 rtOverBusCurrentWarningThr = Uint16.zero; // 实时过流报警阈值
  Uint16 rtPhaseCurrentLimit = Uint16.zero; // 实时相电流限流值

  @override
  void initCompact() {
    compact = _DefaultV13RealTimeInfo();
  }

  @override
  String toString() {
    return 'V13RealTimeInfo{${super.toString()}, chargeVoltage: $chargeVoltage, chargeCurrent: $chargeCurrent, acceleration: $acceleration, batteryMaxCellTemp: $batteryMaxCellTemp, '
        'batteryMaxBmsTemp: $batteryMaxBmsTemp, rtOverSpeedTiltBackThr: $rtOverSpeedTiltBackThr, rtOverSpeedWarningThr: $rtOverSpeedWarningThr, '
        'rtOverOutputTiltBackThr: $rtOverOutputTiltBackThr, rtOverOutputWarningThr: $rtOverOutputWarningThr, rtOverBusCurrentTiltBackThr: $rtOverBusCurrentTiltBackThr, '
        'rtOverBusCurrentWarningThr: $rtOverBusCurrentWarningThr, rtPhaseCurrentLimit: $rtPhaseCurrentLimit}';
  }
}

class _DefaultV13RealTimeInfo extends Compact<V13RealTimeInfo> {
  @override
  void fromBytes(V13RealTimeInfo output, Uint8ClampedList bytes, int offset) {
    if (bytes.length < offset + output.length()) {
      return;
    }

    output.voltage = ByteUtil.bytes2Int16Le(bytes, offset);
    offset += 2;
    output.current = ByteUtil.bytes2Int16Le(bytes, offset);
    offset += 2;
    output.chargeVoltage = ByteUtil.bytes2Int16Le(bytes, offset);
    offset += 2;
    output.chargeCurrent = ByteUtil.bytes2Int16Le(bytes, offset);
    offset += 2;

    output.speed = ByteUtil.bytes2Int16Le(bytes, offset);
    offset += 2;
    output.acceleration = ByteUtil.bytes2Int16Le(bytes, offset);
    offset += 2;
    output.torque = ByteUtil.bytes2Int16Le(bytes, offset);
    offset += 2;
    output.outputRate = ByteUtil.bytes2Int16Le(bytes, offset);
    offset += 2;
    output.batteryOutputPower = ByteUtil.bytes2Int16Le(bytes, offset);
    offset += 2;
    output.motorOutputPower = ByteUtil.bytes2Int16Le(bytes, offset);
    offset += 2;
    output.pitchAngle = ByteUtil.bytes2Int16Le(bytes, offset);
    offset += 2;
    output.rollAngle = ByteUtil.bytes2Int16Le(bytes, offset);
    offset += 2;
    output.pitchAimAngle = ByteUtil.bytes2Int16Le(bytes, offset);
    offset += 2;
    output.speedingBrakingAngle = ByteUtil.bytes2Int16Le(bytes, offset);
    offset += 2;
    output.mileage = ByteUtil.bytes2Uint16Le(bytes, offset);
    offset += 2;

    // 保留4byte
    offset += 4;

    output.batteryLevel = ByteUtil.bytes2Uint16Le(bytes, offset);
    offset += 2;
    output.batteryLevelForRide = ByteUtil.bytes2Uint16Le(bytes, offset);
    offset += 2;

    output.estimatedTotalMileage = ByteUtil.bytes2Uint16Le(bytes, offset);
    output.remainderRange = Uint16(((output.batteryLevelForRide.value / 10000) * output.estimatedTotalMileage.value).toInt());
    offset += 2;

    output.rtOverSpeedTiltBackThr = ByteUtil.bytes2Uint16Le(bytes, offset);
    // 使用翘板速度作为动态限速值
    output.dynamicSpeedLimit = output.rtOverSpeedTiltBackThr;
    offset += 2;
    output.rtOverSpeedWarningThr = ByteUtil.bytes2Uint16Le(bytes, offset);
    offset += 2;
    output.rtOverOutputTiltBackThr = ByteUtil.bytes2Uint16Le(bytes, offset);
    offset += 2;
    output.rtOverOutputWarningThr = ByteUtil.bytes2Uint16Le(bytes, offset);
    offset += 2;
    output.rtOverBusCurrentTiltBackThr = ByteUtil.bytes2Uint16Le(bytes, offset);
    offset += 2;
    output.rtOverBusCurrentWarningThr = ByteUtil.bytes2Uint16Le(bytes, offset);
    offset += 2;
    output.rtPhaseCurrentLimit = ByteUtil.bytes2Uint16Le(bytes, offset);
    offset += 2;

    // 保留4byte
    offset += 4;

    output.mosTemp = ByteUtil.toInt16(ByteUtil.toInt8Int(bytes[offset]) + 80);
    offset++;
    output.motorTemp = ByteUtil.toInt16(ByteUtil.toInt8Int(bytes[offset]) + 80);
    offset++;
    output.batteryTemp = ByteUtil.toInt16(ByteUtil.toInt8Int(bytes[offset]) + 80);
    offset++;
    output.boardTemp = ByteUtil.toInt16(ByteUtil.toInt8Int(bytes[offset]) + 80);
    offset++;
    output.cpuTemp = ByteUtil.toInt16(ByteUtil.toInt8Int(bytes[offset]) + 80);
    offset++;
    output.imuTemp = ByteUtil.toInt16(ByteUtil.toInt8Int(bytes[offset]) + 80);
    offset++;

    output.batteryMaxCellTemp = ByteUtil.toInt8(ByteUtil.toInt8Int(bytes[offset]) + 80);
    offset++;
    output.batteryMaxBmsTemp = ByteUtil.toInt8(ByteUtil.toInt8Int(bytes[offset]) + 80);
    offset++;
    output.lampTemp = ByteUtil.toInt16(ByteUtil.toInt8Int(bytes[offset]) + 80);
    offset++;
    output.brightness = ByteUtil.toUint8(bytes[offset]);
    offset++;
    output.lightBrightness = ByteUtil.toUint8(bytes[offset]);
    offset++;

    // 保留5byte
  }

  @override
  int length() {
    return 74;
  }
}

/// 实时状态
class V13RealTimeState extends EucRealTimeState {
  Uint4 chargePortDetectState = Uint4.zero;
  Uint4 chargePortOnState = Uint4.zero;
  Uint4 dcPortDetectState = Uint4.zero;
  Uint4 dcOutputEnableState = Uint4.zero;
  Uint4 decorativeLightState = Uint4.zero;

  Uint4 fanState = Uint4.zero;

  V13RealTimeState(ProductModel model, VersionWrapper version) : super(model, version);

  @override
  void initCompact() {
    compact = _DefaultV13RealTimeState();
  }
}

class _DefaultV13RealTimeState extends Compact<V13RealTimeState> {
  @override
  void fromBytes(V13RealTimeState output, Uint8ClampedList bytes, int offset) {
    // 3bit
    output.pcModeValue = ByteUtil.toUint32(ByteUtil.bitValue(bytes[offset], 0, 3).value);
    if (output.pcModeValue.value == 0) {
      output.pcMode = Mode.idle;
    } else if (output.pcModeValue.value == 1) {
      output.pcMode = Mode.working;
    } else if (output.pcModeValue.value == 2) {
      output.pcMode = Mode.sleep;
    } else if (output.pcModeValue.value == 3) {
      output.pcMode = Mode.locked;
    }
    output.lockState = output.pcMode == Mode.locked ? Uint4(1) : Uint4.zero;
    // 3bit
    output.mcMode = ByteUtil.bitValue(bytes[offset], 3, 3);
    // 1bit
    output.motorState = ByteUtil.bitValue(bytes[offset], 6, 1);
    // 1bit
    output.chargeState = ByteUtil.bitValue(bytes[offset], 7, 1);
    offset++;
    // 1bit
    output.backupBatteryState = ByteUtil.bitValue(bytes[offset], 0, 1);
    // 3bit
    output.chargePortDetectState = ByteUtil.bitValue(bytes[offset], 1, 3);
    // 1bit
    output.chargePortOnState = ByteUtil.bitValue(bytes[offset], 4, 1);
    // 3bit
    output.dcPortDetectState = ByteUtil.bitValue(bytes[offset], 5, 3);
    offset++;
    // 1bit
    output.dcOutputEnableState = ByteUtil.bitValue(bytes[offset], 0, 1);
    // 1bit
    output.headlightState = ByteUtil.bitValue(bytes[offset], 1, 1);
    // 1bit
    output.decorativeLightState = ByteUtil.bitValue(bytes[offset], 2, 1);
    // 1bit
    output.liftedState = ByteUtil.bitValue(bytes[offset], 3, 1);
    // 3bit
    output.tailLightState = ByteUtil.bitValue(bytes[offset], 4, 3);
    // 1bit
    output.fanState = ByteUtil.bitValue(bytes[offset], 7, 1);
    offset++;
    output.brakeState = ByteUtil.bitValue(bytes[offset], 0, 1);
    output.slowDownState = ByteUtil.bitValue(bytes[offset], 1, 1);
    output.dfuState = ByteUtil.bitValue(bytes[offset], 2, 1);
    // 剩余保留
  }

  @override
  int length() {
    return 4;
  }
}

/// 实时故障和警告
class V13RealTimeError extends EucRealTimeError {
  Uint4 motorHall1State = Uint4.zero;
  Uint4 motorHall2State = Uint4.zero;

  Uint4 batteryComLostState = Uint4.zero; // 电池通讯丢失
  Uint4 batteryCrossComLostState = Uint4.zero; // 电池间通讯丢失

  Uint4 batteryWarningState = Uint4.zero; // 电池警告状态
  Uint4 batteryProtectState = Uint4.zero; // 电池保护状态
  Uint4 chargeOverCurrentState = Uint4.zero; // 充电过流状态
  Uint4 dcOutputOverCurrentState = Uint4.zero; // DC输出过流状态

  Uint4 hwOverCurrentState = Uint4.zero; // 硬件过流保护状态

  V13RealTimeError(ProductModel model, VersionWrapper version) : super(model, version);

  @override
  void initCompact() {
    compact = _DefaultV13RealTimeError();
  }
}

class _DefaultV13RealTimeErrorImpl<T extends V13RealTimeError> extends Compact<T> {
  @override
  void fromBytes(T output, Uint8ClampedList bytes, int offset) {
    output.originalValue = ByteUtil.bytes2Int32Le(bytes, offset);

    output.iPhaseSensorState = ByteUtil.bitValue(bytes[offset], 0, 1);
    output.iBusSensorState = ByteUtil.bitValue(bytes[offset], 1, 1);
    output.motorHall1State = ByteUtil.bitValue(bytes[offset], 2, 1);
    output.motorHall2State = ByteUtil.bitValue(bytes[offset], 3, 1);
    output.batteryState = ByteUtil.bitValue(bytes[offset], 4, 1);
    output.imuSensorState = ByteUtil.bitValue(bytes[offset], 5, 1);
    output.controllerCom1State = ByteUtil.bitValue(bytes[offset], 6, 1);
    output.controllerCom2State = ByteUtil.bitValue(bytes[offset], 7, 1);
    offset++;

    output.bleCom1State = ByteUtil.bitValue(bytes[offset], 0, 1);
    output.bleCom2State = ByteUtil.bitValue(bytes[offset], 1, 1);
    output.batteryComLostState = ByteUtil.bitValue(bytes[offset], 2, 1);
    output.batteryCrossComLostState = ByteUtil.bitValue(bytes[offset], 3, 1);
    output.mosTempSensorState = ByteUtil.bitValue(bytes[offset], 4, 1);
    output.motorTempSensorState = ByteUtil.bitValue(bytes[offset], 5, 1);
    output.boardTempSensorState = ByteUtil.bitValue(bytes[offset], 6, 1);
    output.fanState = ByteUtil.bitValue(bytes[offset], 7, 1);
    offset++;
    output.rtcState = ByteUtil.bitValue(bytes[offset], 0, 1);
    output.externalRomState = ByteUtil.bitValue(bytes[offset], 1, 1);
    output.vBusSensorState = ByteUtil.bitValue(bytes[offset], 2, 1);
    output.vBatterySensorState = ByteUtil.bitValue(bytes[offset], 3, 1);
    output.canNotPowerOffState = ByteUtil.bitValue(bytes[offset], 4, 1);
    output.canNotChargeState = ByteUtil.bitValue(bytes[offset], 5, 1);
    // 剩余2bit保留
    // 剩余1byte保留
    offset++;

    offset++;

    // 警告
    output.underVoltageState = ByteUtil.bitValue(bytes[offset], 0, 1);
    output.overVoltageState = ByteUtil.bitValue(bytes[offset], 1, 1);
    output.overBusCurrentState = ByteUtil.bitValue(bytes[offset], 2, 2);
    output.lowBatteryState = ByteUtil.bitValue(bytes[offset], 4, 2);
    output.overMosTempState = ByteUtil.bitValue(bytes[offset], 6, 1);
    output.overMotorTempState = ByteUtil.bitValue(bytes[offset], 7, 1);
    offset++;

    output.overBoardTempState = ByteUtil.bitValue(bytes[offset], 0, 1);
    output.cpuOverTempState = ByteUtil.bitValue(bytes[offset], 1, 1);
    output.imuOverTempState = ByteUtil.bitValue(bytes[offset], 2, 1);
    output.overSpeedState = ByteUtil.bitValue(bytes[offset], 3, 1);
    output.outputSaturationState = ByteUtil.bitValue(bytes[offset], 4, 1);
    output.motorSpinState = ByteUtil.bitValue(bytes[offset], 5, 1);
    output.motorBlockState = ByteUtil.bitValue(bytes[offset], 6, 1);
    output.postureState = ByteUtil.bitValue(bytes[offset], 7, 1);
    offset++;

    output.riskBehaviourState = ByteUtil.bitValue(bytes[offset], 0, 1);
    output.motorNoLoadState = ByteUtil.bitValue(bytes[offset], 1, 1);
    output.noSelfTestState = ByteUtil.bitValue(bytes[offset], 2, 1);
    output.powerKeyLongPressState = ByteUtil.bitValue(bytes[offset], 3, 1);
    output.someBatteriesNotWorkState = ByteUtil.bitValue(bytes[offset], 4, 1);
    output.batteryNotCaliState = ByteUtil.bitValue(bytes[offset], 5, 1);
    output.batteryWarningState = ByteUtil.bitValue(bytes[offset], 6, 1);
    output.batteryProtectState = ByteUtil.bitValue(bytes[offset], 7, 1);
    offset++;

    output.chargeOverCurrentState = ByteUtil.bitValue(bytes[offset], 0, 1);
    output.dcOutputOverCurrentState = ByteUtil.bitValue(bytes[offset], 1, 1);
    output.compatibilityState = ByteUtil.bitValue(bytes[offset], 2, 1);
    output.forceDfuState = ByteUtil.bitValue(bytes[offset], 3, 1);
    output.deviceLockState = ByteUtil.bitValue(bytes[offset], 4, 1);
    output.hwCompatibilityState = ByteUtil.bitValue(bytes[offset], 5, 1);
    output.fanLowSpeedState = ByteUtil.bitValue(bytes[offset], 6, 1);
    output.hwOverCurrentState = ByteUtil.bitValue(bytes[offset], 7, 1);
  }

  @override
  int length() {
    return 8;
  }
}

class _DefaultV13RealTimeError<V13RealTimeError> extends _DefaultV13RealTimeErrorImpl {}

class DefaultV13RealTimeErrorDelegate<T extends V13RealTimeError> extends _DefaultV13RealTimeErrorImpl<T> {}

class V13BatteryRealTimeInfo extends AbsBatteryRealTimeInfo {
  V13SingleBatteryRealTimeInfo? _battery1;
  V13SingleBatteryRealTimeInfo? _battery2;

  V13BatteryRealTimeInfo(ProductModel model, VersionWrapper version) : super(model, version);

  @override
  void initCompact() {
    compact = _DefaultV13BatteryRealTimeInfo(model, version);
  }

  get battery1 {
    if (_battery1 == null) throw ProtocolParseException("Unexpected exception. Please call [fromBytes] to gen battery info first!");
    return _battery1!;
  }

  get battery2 {
    if (_battery2 == null) throw ProtocolParseException("Unexpected exception. Please call [fromBytes] to gen battery info first!");
    return _battery2!;
  }

  @override
  String toString() {
    return 'V13BatteryRealTimeInfo{_battery1: $_battery1, _battery2: $_battery2}';
  }
}

class _DefaultV13BatteryRealTimeInfo extends Compact<V13BatteryRealTimeInfo> {
  final ProductModel _model;
  final VersionWrapper _versionWrapper;

  _DefaultV13BatteryRealTimeInfo(this._model, this._versionWrapper);

  @override
  void fromBytes(V13BatteryRealTimeInfo output, Uint8ClampedList bytes, int offset) {
    output._battery1 = V13SingleBatteryRealTimeInfo(_model, _versionWrapper);
    output._battery1!.fromBytes(bytes, offset);
    offset += output._battery1!.length();
    output._battery2 = V13SingleBatteryRealTimeInfo(_model, _versionWrapper);
    output._battery2!.fromBytes(bytes, offset);
  }

  @override
  int length() {
    return 16;
  }
}

class V13SingleBatteryRealTimeInfo extends AbsBatteryRealTimeInfo {
  Uint16 voltage = Uint16.zero;
  Int16 chargeCurrent = Int16.zero;
  Int16 dischargeCurrent = Int16.zero;

  Uint4 detected = Uint4.zero;
  Uint4 enable = Uint4.zero;
  Uint4 charge = Uint4.zero;

  Uint4 errorLogic = Uint4.zero;
  Uint4 errorSignal = Uint4.zero;
  Uint4 errorVoltageSensor = Uint4.zero;
  Uint4 errorCurrentSensor = Uint4.zero;
  Uint4 errorCannotCharge = Uint4.zero;
  Uint4 batteryWarning = Uint4.zero;
  Uint4 batteryProtect = Uint4.zero;
  Uint4 batteryError = Uint4.zero;

  V13SingleBatteryRealTimeInfo(ProductModel model, VersionWrapper version) : super(model, version);

  @override
  void initCompact() {
    compact = _DefaultV13SingleBatteryRealTimeInfo();
  }

  @override
  String toString() {
    return 'V13SingleBatteryRealTimeInfo{voltage: $voltage, chargeCurrent: $chargeCurrent, dischargeCurrent: $dischargeCurrent, detected: $detected, enable: $enable, charge: $charge, errorLogic: $errorLogic, errorSignal: $errorSignal, errorVoltageSensor: $errorVoltageSensor, errorCurrentSensor: $errorCurrentSensor, errorCannotCharge: $errorCannotCharge, batteryWarning: $batteryWarning, batteryProtect: $batteryProtect, batteryError: $batteryError}';
  }
}

class _DefaultV13SingleBatteryRealTimeInfo extends Compact<V13SingleBatteryRealTimeInfo> {
  @override
  void fromBytes(V13SingleBatteryRealTimeInfo output, Uint8ClampedList bytes, int offset) {
    output.voltage = ByteUtil.bytes2Uint16Le(bytes, offset);
    offset += 2;
    output.chargeCurrent = ByteUtil.bytes2Int16Le(bytes, offset);
    offset += 2;
    output.dischargeCurrent = ByteUtil.bytes2Int16Le(bytes, offset);
    offset += 2;

    output.detected = ByteUtil.bitValue(bytes[offset], 0, 1);
    output.enable = ByteUtil.bitValue(bytes[offset], 1, 1);
    output.charge = ByteUtil.bitValue(bytes[offset], 2, 1);
    // 剩余3bit保留
    output.errorLogic = ByteUtil.bitValue(bytes[offset], 6, 1);
    output.errorSignal = ByteUtil.bitValue(bytes[offset], 7, 1);

    offset++;

    output.errorVoltageSensor = ByteUtil.bitValue(bytes[offset], 0, 1);
    output.errorCurrentSensor = ByteUtil.bitValue(bytes[offset], 1, 1);
    output.errorCannotCharge = ByteUtil.bitValue(bytes[offset], 2, 1);
    output.batteryWarning = ByteUtil.bitValue(bytes[offset], 3, 1);
    output.batteryProtect = ByteUtil.bitValue(bytes[offset], 4, 1);
    output.batteryError = ByteUtil.bitValue(bytes[offset], 5, 1);
    // 剩余2bit保留
  }

  @override
  int length() {
    return 8;
  }
}
